home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / src / binutils.252 / gprof / gprof.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-30  |  18.8 KB  |  792 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that: (1) source distributions retain this entire copyright
  7.  * notice and comment, and (2) distributions including binaries display
  8.  * the following acknowledgement:  ``This product includes software
  9.  * developed by the University of California, Berkeley and its contributors''
  10.  * in the documentation or other materials provided with the distribution
  11.  * and in all advertising materials mentioning features or use of this
  12.  * software. Neither the name of the University nor the names of its
  13.  * contributors may be used to endorse or promote products derived
  14.  * from this software without specific prior written permission.
  15.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  16.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  17.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18.  */
  19.  
  20. #define VERSION "5.6 (Cygnus)"
  21.  
  22. #ifndef lint
  23. char copyright[] =
  24. "@(#) Copyright (c) 1983 Regents of the University of California.\n\
  25.  All rights reserved.\n";
  26. #endif /* not lint */
  27.  
  28. #ifndef lint
  29. static char sccsid[] = "@(#)gprof.c    5.6 (Berkeley) 6/1/90";
  30. #endif /* not lint */
  31.  
  32. #include "gprof.h"
  33.  
  34. #ifndef FOPEN_RB
  35. #define FOPEN_RB "r"
  36. #endif
  37.  
  38. bfd    *abfd;
  39.  
  40. char    *whoami;
  41.  
  42.     /*
  43.      *    things which get -E excluded by default.
  44.      */
  45. char    *defaultEs[] = { "mcount" , "__mcleanup" , 0 };
  46.  
  47. int discard_underscores = 1; /* Should we discard initial underscores? */
  48. int bsd_style_output = 0; /* As opposed to FSF style output */
  49.  
  50. main(argc, argv)
  51.     int argc;
  52.     char **argv;
  53. {
  54.     char    **sp;
  55.     nltype    **timesortnlp;
  56.  
  57.     whoami = argv[0];
  58.     --argc;
  59.     argv++;
  60.     debug = 0;
  61.     bflag = TRUE;
  62.     while ( *argv != 0 && **argv == '-' ) {
  63.     (*argv)++;
  64.     switch ( **argv ) {
  65.     case 'a':
  66.         aflag = TRUE;
  67.         break;
  68.     case 'b':
  69.         bflag = FALSE;
  70.         break;
  71.     case 'c':
  72.         cflag = TRUE;
  73.         break;
  74.     case 'd':
  75.         dflag = TRUE;
  76.         (*argv)++;
  77.         debug |= atoi( *argv );
  78.         debug |= ANYDEBUG;
  79. #        ifdef DEBUG
  80.         printf("[main] debug = %d\n", debug);
  81. #        else not DEBUG
  82.         printf("%s: -d ignored\n", whoami);
  83. #        endif DEBUG
  84.         break;
  85.     case 'E':
  86.         ++argv;
  87.         addlist( Elist , *argv );
  88.         Eflag = TRUE;
  89.         addlist( elist , *argv );
  90.         eflag = TRUE;
  91.         break;
  92.     case 'e':
  93.         addlist( elist , *++argv );
  94.         eflag = TRUE;
  95.         break;
  96.     case 'F':
  97.         ++argv;
  98.         addlist( Flist , *argv );
  99.         Fflag = TRUE;
  100.         addlist( flist , *argv );
  101.         fflag = TRUE;
  102.         break;
  103.     case 'f':
  104.         addlist( flist , *++argv );
  105.         fflag = TRUE;
  106.         break;
  107.     case 'k':
  108.         addlist( kfromlist , *++argv );
  109.         addlist( ktolist , *++argv );
  110.         kflag = TRUE;
  111.         break;
  112.     case 's':
  113.         sflag = TRUE;
  114.         break;
  115.     case 'T': /* "Traditional" output format */
  116.         bsd_style_output = 1;
  117.         break;
  118.         case 'v':
  119.         printf ("gprof version %s\n", VERSION);
  120.         exit(0);
  121.         break;
  122.     case 'z':
  123.         zflag = TRUE;
  124.         break;
  125.     default:
  126.         fprintf (stderr, "\
  127. Usage: %s [-a] [-b] [-c] [-d[num]] [-E function-name] [-e function-name]\n\
  128.        [-F function-name] [-f function-name] [-k from to] [-s] [-T] [-z]\n\
  129.        [image-file] [profile-file...]\n", whoami);
  130.         exit (1);
  131.     }
  132.     argv++;
  133.     }
  134.     if ( *argv != 0 ) {
  135.     a_outname  = *argv;
  136.     argv++;
  137.     } else {
  138.     a_outname  = A_OUTNAME;
  139.     }
  140.     if ( *argv != 0 ) {
  141.     gmonname = *argv;
  142.     argv++;
  143.     } else {
  144.     gmonname = GMONNAME;
  145.     }
  146.     /*
  147.      *    turn off default functions
  148.      */
  149.     for ( sp = &defaultEs[0] ; *sp ; sp++ ) {
  150.     Eflag = TRUE;
  151.     addlist( Elist , *sp );
  152.     eflag = TRUE;
  153.     addlist( elist , *sp );
  154.     }
  155.     /*
  156.      *    how many ticks per second?
  157.      *    if we can't tell, report time in ticks.
  158.      */
  159.     hz = hertz();
  160.     if (hz == 0) {
  161.     hz = 1;
  162.     fprintf(stderr, "time is in ticks, not seconds\n");
  163.     }
  164.     /*
  165.      *    get information about a.out file.
  166.      */
  167.     getnfile();
  168.     /*
  169.      *    get information about mon.out file(s).
  170.      */
  171.     do    {
  172.     getpfile( gmonname );
  173.     if ( *argv != 0 ) {
  174.         gmonname = *argv;
  175.     }
  176.     } while ( *argv++ != 0 );
  177.     /*
  178.      *    dump out a gmon.sum file if requested
  179.      */
  180.     if ( sflag ) {
  181.     dumpsum( GMONSUM );
  182.     }
  183.     /*
  184.      *    assign samples to procedures
  185.      */
  186.     asgnsamples();
  187.     /*
  188.      *    assemble the dynamic profile
  189.      */
  190.     timesortnlp = doarcs();
  191.     
  192.     if (bsd_style_output) {
  193.     printgprof( timesortnlp );    /* print the dynamic profile */
  194.     printprof();  /* print the flat profile */
  195.     } else {
  196.     printprof();  /* print the flat profile */
  197.     printgprof( timesortnlp );    /* print the dynamic profile */
  198.     }
  199.     /*
  200.      *    print the index
  201.      */
  202.     printindex();    
  203.     done();
  204. }
  205.  
  206.     /*
  207.      * Set up string and symbol tables from a.out.
  208.      *    and optionally the text space.
  209.      * On return symbol table is sorted by value.
  210.      */
  211. getnfile()
  212. {
  213.   int        valcmp();
  214.  
  215.   abfd = bfd_openr (a_outname, NULL);
  216.  
  217.   if (abfd == NULL) {
  218.     perror (a_outname);
  219.     done();
  220.   }
  221.  
  222.   if (!bfd_check_format (abfd, bfd_object)) {
  223.     fprintf (stderr, "%s: %s: bad format\n", whoami, a_outname);
  224.     done();
  225.   }
  226.  
  227. /*  getstrtab(nfile); */
  228.   getsymtab(abfd);
  229.   gettextspace( abfd );
  230.   qsort(nl, nname, sizeof(nltype), valcmp);
  231.  
  232. #   ifdef DEBUG
  233.   if ( debug & AOUTDEBUG ) {
  234.     register int j;
  235.     
  236.     for (j = 0; j < nname; j++){
  237.       printf("[getnfile] 0X%08x\t%s\n", nl[j].value, nl[j].name);
  238.     }
  239.   }
  240. #   endif DEBUG
  241. }
  242.  
  243. /*
  244.  * Read in symbol table
  245.  */
  246. getsymtab(abfd)
  247. bfd    *abfd;
  248. {
  249.     register long    i;
  250.     int            askfor;
  251.     long        nosyms;
  252.     asymbol        **syms;
  253.     i = bfd_get_symtab_upper_bound (abfd);/* This will probably give us more
  254.                        * than we need, but that's ok.
  255.                        */
  256.     if (i < 0)
  257.       {
  258.     fprintf (stderr, "%s: %s: %s\n", whoami, a_outname,
  259.          bfd_errmsg (bfd_get_error ()));
  260.     exit (1);
  261.       }
  262.     syms = (asymbol**)xmalloc (i);
  263.     nosyms = bfd_canonicalize_symtab (abfd, syms);
  264.     if (nosyms < 0)
  265.       {
  266.     fprintf (stderr, "%s: %s: %s\n", whoami, a_outname,
  267.          bfd_errmsg (bfd_get_error ()));
  268.     exit (1);
  269.       }
  270.  
  271.     nname = 0;
  272.     for (i = 0; i < nosyms; i++) {
  273.       if (!funcsymbol (syms[i]))
  274.     continue;
  275.       nname++;
  276.     }
  277.  
  278.     if (nname == 0) {
  279.       fprintf(stderr, "%s: %s: no symbols\n", whoami , a_outname );
  280.       done();
  281.     }
  282.     askfor = nname + 1;
  283.     nl = (nltype *) calloc( askfor , sizeof(nltype) );
  284.     if (nl == 0) {
  285.     fprintf(stderr, "%s: No room for %d bytes of symbol table\n",
  286.         whoami, askfor * sizeof(nltype) );
  287.     done();
  288.     }
  289.  
  290.     /* pass2 - read symbols */
  291.     npe = nl;
  292.     nname = 0;
  293.     for (i = 0; i < nosyms; i++) {
  294.       if (!funcsymbol (syms[i])) {
  295. #        ifdef DEBUG
  296.     if ( debug & AOUTDEBUG ) {
  297.       printf( "[getsymtab] rejecting: 0x%x %s\n" ,
  298.          syms[i]->value, syms[i]->name);
  299.     }
  300. #        endif DEBUG
  301.     continue;
  302.       }
  303.       /* Symbol offsets are always section-relative. */
  304.       npe->value = syms[i]->value + syms[i]->section->vma;
  305.       npe->name = syms[i]->name;
  306.  
  307.       /* If we see "main" without an initial '_', we assume
  308.      names are *not* prefixed by '_'. */
  309.       if (npe->name[0] == 'm' && discard_underscores
  310.       && strcmp(npe->name, "main") == 0)
  311.       discard_underscores = 0;
  312.  
  313. #    ifdef DEBUG
  314.       if ( debug & AOUTDEBUG ) {
  315.     printf( "[getsymtab] %d %s 0x%08x\n" ,
  316.            nname , npe -> name , npe -> value );
  317.       }
  318. #    endif DEBUG
  319.       npe++;
  320.       nname++;
  321.     }
  322.     npe->value = -1;
  323. }
  324.  
  325. /*
  326.  *    read in the text space of an a.out file
  327.  */
  328. gettextspace( abfd )
  329.      bfd    *abfd;
  330. {
  331.   asection    *texsec;
  332.     
  333.   if ( cflag == 0 ) {
  334.     return;
  335.   }
  336.  
  337.   texsec = bfd_get_section_by_name (abfd, ".text");
  338.   if (texsec == NULL) {
  339.     return;
  340.   }
  341.  
  342.   textspace = (u_char *) malloc( texsec->_cooked_size );
  343.  
  344.   if ( textspace == 0 ) {
  345.     fprintf( stderr , "%s: ran out room for %d bytes of text space:  " ,
  346.         whoami , texsec->_cooked_size);
  347.     fprintf( stderr , "can't do -c\n" );
  348.     return;
  349.   }
  350.   bfd_get_section_contents (abfd, texsec, textspace, texsec->filepos, 
  351.                 texsec->_cooked_size);
  352. }
  353. /*
  354.  *    information from a gmon.out file is in two parts:
  355.  *    an array of sampling hits within pc ranges,
  356.  *    and the arcs.
  357.  */
  358. getpfile(filename)
  359.     char *filename;
  360. {
  361.     FILE        *pfile;
  362.     FILE        *openpfile();
  363.     struct rawarc    arc;
  364.     struct veryrawarc    rawarc;
  365.  
  366.     pfile = openpfile(filename);
  367.     readsamples(pfile);
  368.     /*
  369.      *    the rest of the file consists of
  370.      *    a bunch of <from,self,count> tuples.
  371.      */
  372.     while ( fread( &rawarc , sizeof rawarc , 1 , pfile ) == 1 ) {
  373.       arc.raw_frompc = bfd_get_32 (abfd, (bfd_byte *) rawarc.raw_frompc);
  374.       arc.raw_selfpc = bfd_get_32 (abfd, (bfd_byte *) rawarc.raw_selfpc);
  375.       arc.raw_count  = bfd_get_32 (abfd, (bfd_byte *) rawarc.raw_count);
  376. #    ifdef DEBUG
  377.         if ( debug & SAMPLEDEBUG ) {
  378.         printf( "[getpfile] frompc 0x%x selfpc 0x%x count %d\n" ,
  379.             arc.raw_frompc , arc.raw_selfpc , arc.raw_count );
  380.         }
  381. #    endif DEBUG
  382.         /*
  383.          *    add this arc
  384.          */
  385.     tally( &arc );
  386.     }
  387.     fclose(pfile);
  388. }
  389.  
  390. FILE *
  391. openpfile(filename)
  392.     char *filename;
  393. {
  394.     struct hdr    tmp;
  395.     struct rawhdr raw;
  396.     FILE    *pfile;
  397.  
  398.     if((pfile = fopen(filename, FOPEN_RB)) == NULL) {
  399.     perror(filename);
  400.     done();
  401.     }
  402.     if (sizeof(struct rawhdr) !=  fread(&raw, 1, sizeof(struct rawhdr), pfile))
  403.       {
  404.     fprintf(stderr, "%s: file too short to be a gmon file\n", filename);
  405.     done();
  406.       }    
  407.     tmp.lowpc  = (UNIT *)bfd_get_32 (abfd, (bfd_byte *) &raw.lowpc[0]);
  408.     tmp.highpc = (UNIT *)bfd_get_32 (abfd, (bfd_byte *) &raw.highpc[0]);
  409.     tmp.ncnt   =         bfd_get_32 (abfd, (bfd_byte *) &raw.ncnt[0]);
  410.  
  411.     if ( s_highpc != 0 && ( tmp.lowpc != h.lowpc ||
  412.      tmp.highpc != h.highpc || tmp.ncnt != h.ncnt ) ) {
  413.     fprintf(stderr, "%s: incompatible with first gmon file\n", filename);
  414.     done();
  415.     }
  416.     h = tmp;
  417.     s_lowpc = (unsigned long) h.lowpc;
  418.     s_highpc = (unsigned long) h.highpc;
  419.     lowpc = (unsigned long)h.lowpc / sizeof(UNIT);
  420.     highpc = (unsigned long)h.highpc / sizeof(UNIT);
  421.     sampbytes = h.ncnt - sizeof(struct rawhdr);
  422.     nsamples = sampbytes / sizeof (UNIT);
  423. #   ifdef DEBUG
  424.     if ( debug & SAMPLEDEBUG ) {
  425.         printf( "[openpfile] hdr.lowpc 0x%x hdr.highpc 0x%x hdr.ncnt %d\n",
  426.         h.lowpc , h.highpc , h.ncnt );
  427.         printf( "[openpfile]   s_lowpc 0x%x   s_highpc 0x%x\n" ,
  428.         s_lowpc , s_highpc );
  429.         printf( "[openpfile]     lowpc 0x%x     highpc 0x%x\n" ,
  430.         lowpc , highpc );
  431.         printf( "[openpfile] sampbytes %d nsamples %d\n" ,
  432.         sampbytes , nsamples );
  433.     }
  434. #   endif DEBUG
  435.     return(pfile);
  436. }
  437.  
  438. tally( rawp )
  439.     struct rawarc    *rawp;
  440. {
  441.     nltype        *parentp;
  442.     nltype        *childp;
  443.  
  444.     parentp = nllookup( rawp -> raw_frompc );
  445.     childp = nllookup( rawp -> raw_selfpc );
  446.     if ( kflag
  447.      && onlist( kfromlist , parentp -> name )
  448.      && onlist( ktolist , childp -> name ) ) {
  449.     return;
  450.     }
  451.     childp -> ncall += rawp -> raw_count;
  452. #   ifdef DEBUG
  453.     if ( debug & TALLYDEBUG ) {
  454.         printf( "[tally] arc from %s to %s traversed %d times\n" ,
  455.             parentp -> name , childp -> name , rawp -> raw_count );
  456.     }
  457. #   endif DEBUG
  458.     addarc( parentp , childp , rawp -> raw_count );
  459. }
  460.  
  461. /*
  462.  * dump out the gmon.sum file
  463.  */
  464. dumpsum( sumfile )
  465.     char *sumfile;
  466. {
  467.     register nltype *nlp;
  468.     register arctype *arcp;
  469.     struct rawarc arc;
  470.     FILE *sfile;
  471.  
  472.     if ( ( sfile = fopen ( sumfile , "w" ) ) == NULL ) {
  473.     perror( sumfile );
  474.     done();
  475.     }
  476.     /*
  477.      * dump the header; use the last header read in
  478.      */
  479.     if ( fwrite( &h , sizeof h , 1 , sfile ) != 1 ) {
  480.     perror( sumfile );
  481.     done();
  482.     }
  483.     /*
  484.      * dump the samples
  485.      */
  486.     if (fwrite(samples, sizeof (UNIT), nsamples, sfile) != nsamples) {
  487.     perror( sumfile );
  488.     done();
  489.     }
  490.     /*
  491.      * dump the normalized raw arc information
  492.      */
  493.     for ( nlp = nl ; nlp < npe ; nlp++ ) {
  494.     for ( arcp = nlp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
  495.         arc.raw_frompc = arcp -> arc_parentp -> value;
  496.         arc.raw_selfpc = arcp -> arc_childp -> value;
  497.         arc.raw_count = arcp -> arc_count;
  498.         if ( fwrite ( &arc , sizeof arc , 1 , sfile ) != 1 ) {
  499.         perror( sumfile );
  500.         done();
  501.         }
  502. #        ifdef DEBUG
  503.         if ( debug & SAMPLEDEBUG ) {
  504.             printf( "[dumpsum] frompc 0x%x selfpc 0x%x count %d\n" ,
  505.                 arc.raw_frompc , arc.raw_selfpc , arc.raw_count );
  506.         }
  507. #        endif DEBUG
  508.     }
  509.     }
  510.     fclose( sfile );
  511. }
  512.  
  513. valcmp(p1, p2)
  514.     nltype *p1, *p2;
  515. {
  516.     if ( p1 -> value < p2 -> value ) {
  517.     return LESSTHAN;
  518.     }
  519.     if ( p1 -> value > p2 -> value ) {
  520.     return GREATERTHAN;
  521.     }
  522.     return EQUALTO;
  523. }
  524.  
  525. readsamples(pfile)
  526.     FILE    *pfile;
  527. {
  528.   register int i;
  529.  
  530.     
  531.   if (samples == 0) {
  532.     samples = (int *) calloc (nsamples, sizeof(int));
  533.     if (samples == 0) {
  534.       fprintf( stderr , "%s: No room for %d sample pc's\n", 
  535.           whoami , nsamples);
  536.       done();
  537.     }
  538.   }
  539.   for (i = 0; i < nsamples; i++) {
  540.     UNIT    raw;
  541.     int value;
  542.       
  543.     fread(raw, sizeof (raw), 1, pfile);
  544.     value = bfd_get_16 (abfd, (bfd_byte *) raw);
  545.     if (feof(pfile))
  546.       break;
  547.     samples[i] += value;
  548.   }
  549.   if (i != nsamples) {
  550.     fprintf(stderr,
  551.         "%s: unexpected EOF after reading %d/%d samples\n",
  552.         whoami , --i , nsamples );
  553.     done();
  554.   }
  555. }
  556.  
  557. /*
  558.  *    Assign samples to the procedures to which they belong.
  559.  *
  560.  *    There are three cases as to where pcl and pch can be
  561.  *    with respect to the routine entry addresses svalue0 and svalue1
  562.  *    as shown in the following diagram.  overlap computes the
  563.  *    distance between the arrows, the fraction of the sample
  564.  *    that is to be credited to the routine which starts at svalue0.
  565.  *
  566.  *        svalue0                                         svalue1
  567.  *           |                                               |
  568.  *           v                                               v
  569.  *
  570.  *           +-----------------------------------------------+
  571.  *           |                           |
  572.  *      |  ->|    |<-        ->|         |<-        ->|    |<-  |
  573.  *      |         |          |         |          |         |
  574.  *      +---------+          +---------+          +---------+
  575.  *
  576.  *      ^         ^          ^         ^          ^         ^
  577.  *      |         |          |         |          |         |
  578.  *     pcl       pch         pcl       pch         pcl       pch
  579.  *
  580.  *    For the vax we assert that samples will never fall in the first
  581.  *    two bytes of any routine, since that is the entry mask,
  582.  *    thus we give call alignentries() to adjust the entry points if
  583.  *    the entry mask falls in one bucket but the code for the routine
  584.  *    doesn't start until the next bucket.  In conjunction with the
  585.  *    alignment of routine addresses, this should allow us to have
  586.  *    only one sample for every four bytes of text space and never
  587.  *    have any overlap (the two end cases, above).
  588.  */
  589. asgnsamples()
  590. {
  591.     register int    j;
  592.     int        ccnt;
  593.     double        time;
  594.     unsigned long    pcl, pch;
  595.     register int    i;
  596.     unsigned long    overlap;
  597.     unsigned long    svalue0, svalue1;
  598.  
  599.     /* read samples and assign to namelist symbols */
  600.     scale = highpc - lowpc;
  601.     scale /= nsamples - 1;
  602.     alignentries();
  603.     for (i = 0, j = 1; i < nsamples; i++) {
  604.     ccnt = samples[i];
  605.     if (ccnt == 0)
  606.         continue;
  607.     pcl = lowpc + scale * i;
  608.     pch = lowpc + scale * (i + 1);
  609.     time = ccnt;
  610. #    ifdef DEBUG
  611.         if ( debug & SAMPLEDEBUG ) {
  612.         printf( "[asgnsamples] pcl 0x%x pch 0x%x ccnt %d\n" ,
  613.             pcl , pch , ccnt );
  614.         }
  615. #    endif DEBUG
  616.     totime += time;
  617.     for (j = j - 1; j < nname; j++) {
  618.         svalue0 = nl[j].svalue;
  619.         svalue1 = nl[j+1].svalue;
  620.         /*
  621.          *    if high end of tick is below entry address, 
  622.          *    go for next tick.
  623.          */
  624.         if (pch < svalue0)
  625.             break;
  626.         /*
  627.          *    if low end of tick into next routine,
  628.          *    go for next routine.
  629.          */
  630.         if (pcl >= svalue1)
  631.             continue;
  632.         overlap = min(pch, svalue1) - max(pcl, svalue0);
  633.         if (overlap > 0) {
  634. #        ifdef DEBUG
  635.             if (debug & SAMPLEDEBUG) {
  636.             printf("[asgnsamples] (0x%x->0x%x-0x%x) %s gets %f ticks %d overlap\n",
  637.                 nl[j].value/sizeof(UNIT), svalue0, svalue1,
  638.                 nl[j].name, 
  639.                 overlap * time / scale, overlap);
  640.             }
  641. #        endif DEBUG
  642.         nl[j].time += overlap * time / scale;
  643.         }
  644.     }
  645.     }
  646. #   ifdef DEBUG
  647.     if (debug & SAMPLEDEBUG) {
  648.         printf("[asgnsamples] totime %f\n", totime);
  649.     }
  650. #   endif DEBUG
  651. }
  652.  
  653.  
  654. unsigned long
  655. min(a, b)
  656.     unsigned long a,b;
  657. {
  658.     if (a<b)
  659.     return(a);
  660.     return(b);
  661. }
  662.  
  663. unsigned long
  664. max(a, b)
  665.     unsigned long a,b;
  666. {
  667.     if (a>b)
  668.     return(a);
  669.     return(b);
  670. }
  671.  
  672.     /*
  673.      *    calculate scaled entry point addresses (to save time in asgnsamples),
  674.      *    and possibly push the scaled entry points over the entry mask,
  675.      *    if it turns out that the entry point is in one bucket and the code
  676.      *    for a routine is in the next bucket.
  677.      */
  678. alignentries()
  679. {
  680.     register struct nl    *nlp;
  681.     unsigned long    bucket_of_entry;
  682.     unsigned long    bucket_of_code;
  683.  
  684.     for (nlp = nl; nlp < npe; nlp++) {
  685.     nlp -> svalue = nlp -> value / sizeof(UNIT);
  686.     bucket_of_entry = (nlp->svalue - lowpc) / scale;
  687.     bucket_of_code = (nlp->svalue + UNITS_TO_CODE - lowpc) / scale;
  688.     if (bucket_of_entry < bucket_of_code) {
  689. #        ifdef DEBUG
  690.         if (debug & SAMPLEDEBUG) {
  691.             printf("[alignentries] pushing svalue 0x%x to 0x%x\n",
  692.                 nlp->svalue, nlp->svalue + UNITS_TO_CODE);
  693.         }
  694. #        endif DEBUG
  695.         nlp->svalue += UNITS_TO_CODE;
  696.     }
  697.     }
  698. }
  699.  
  700. bool
  701. funcsymbol( symp )
  702.      asymbol *symp;
  703. {
  704.   extern char    *strtab;    /* string table from a.out */
  705.   extern int    aflag;        /* if static functions aren't desired */
  706.   CONST char    *name;
  707.   int i;
  708.   char        symprefix;
  709.   symbol_info    syminfo;
  710.  
  711.   /*
  712.    *    must be a text symbol,
  713.    *    and static text symbols don't qualify if aflag set.
  714.    */
  715.   
  716.  
  717.   if (!symp->section)
  718.     return FALSE;
  719.  
  720.   if (aflag && (symp->flags&BSF_LOCAL)) {
  721. #if defined(DEBUG)
  722.     fprintf (stderr, "%s(%d):  %s:  not a function\n", __FILE__, __LINE__, symp->name);
  723. #endif
  724.     return FALSE;
  725.   }
  726.  
  727.  
  728.   symprefix = bfd_get_symbol_leading_char (abfd);
  729.   bfd_get_symbol_info (abfd, symp, &syminfo);
  730.   i = syminfo.type;
  731. #if defined(DEBUG) && 0
  732.   if (i != 'T' && i != 't')
  733.     fprintf (stderr, "%s(%d):  %s is of class %c\n", __FILE__, __LINE__, symp->name, i);
  734. #endif
  735.  
  736.   /*
  737.    * Any external text symbol should be okay.  (Only problem would be
  738.    * variables in the text section.)
  739.    */
  740.  
  741.   if (i == 'T')
  742.     return TRUE;
  743.  
  744.   /*
  745.    * 't' is static text; -a says to ignore it.  So if it's not
  746.    * a static text symbol, *or* it is and the user gave -a, we
  747.    * ignore it.
  748.    */
  749.  
  750.   if (i != 't' || aflag)
  751.     return FALSE;
  752.  
  753.   /*
  754.    *    can't have any `funny' characters in name,
  755.    *    where `funny' includes    `.', .o file names
  756.    *            and    `$', pascal labels.
  757.    */
  758.   if (!symp->name)
  759.     return FALSE;
  760.  
  761.   for (name = symp->name; *name; name++) {
  762.     if ( *name == '.' || *name == '$' ) {
  763.       return FALSE;
  764.     }
  765.   }
  766.  
  767.   /* On systems where the C compiler adds an underscore to all names,
  768.    * static names without underscores seem usually to be labels in
  769.    * hand written assembler in the library.  We don't want these
  770.    * names.  This is certainly necessary on a Sparc running SunOS 4.1
  771.    * (try profiling a program that does a lot of division). I don't
  772.    * know whether it has harmful side effects on other systems.
  773.    * Perhaps it should be made configurable.
  774.    */
  775.  
  776.   if (symprefix && symprefix != *symp->name
  777.       /* Gcc may add special symbols to help gdb figure out the file
  778.      language.  We want to ignore these, since sometimes they
  779.      mask the real function.  (dj@ctron)  */
  780.       || !strncmp (symp->name, "__gnu_compiled", 14)
  781.       || !strncmp (symp->name, "___gnu_compiled", 15))
  782.     return FALSE;
  783.  
  784.   return TRUE;
  785. }
  786.  
  787. done()
  788. {
  789.  
  790.     exit(0);
  791. }
  792.